package server

import (
	"gedis/global"
	"gedis/protocol/codec"
	_ "github.com/golang/protobuf/ptypes/any"
	"github.com/panjf2000/gnet"
	"time"
)

type GedisServer struct {
	*gnet.EventServer
	DB *GedisDB
}

func (gs *GedisServer) React(frame []byte, c gnet.Conn) (out []byte, action gnet.Action) {
	client := c.Context().(*codec.Client)
	request := client.Request
	// 解析真正的请求参数
	codec.AnalyticArgs(frame, request)

	global.GVA_LOG.Infof("[%s] args: %s", client.Addr, request.Args)
	global.GVA_LOG.Infof("key count [%d]", gs.DB.count)

	// Execute specified the command.
	executor, ok := CommandTable[request.Command]
	if !ok {
		global.GVA_LOG.Errorf("unknown command [%d] [%s]", request.Command, request.Args)
	}

	var response *codec.ResponseProtocol
	data, err := executor.Process(request, gs)
	if err != nil {
		errMsg := err.Error()
		response = &codec.ResponseProtocol{
			Result:  '-',
			Version: request.Version,
			Command: request.Command,
			DataLen: int32(len(errMsg)),
			Data:    errMsg,
		}
	} else {
		response = &codec.ResponseProtocol{
			Result:  '+',
			Version: request.Version,
			Command: request.Command,
			DataLen: int32(len(data)),
			Data:    data,
		}
	}

	c.SetContext(response)

	out = frame
	return
}

func Start() {
	gedis := &GedisServer{
		DB: NewGedisDB(),
	}
	codec := codec.NewGedisProtocolCodec()
	global.GVA_LOG.Infof("server bind port %s", global.GVA_NETWORK.Port)
	err := gnet.Serve(
		gedis,
		"tcp://:"+global.GVA_NETWORK.Port,
		gnet.WithCodec(codec),
		gnet.WithNumEventLoop(1),
		gnet.WithTCPKeepAlive(global.GVA_NETWORK.TcpKeepalive*time.Second))
	if err != nil {
		panic(err)
	}
}
